﻿using Abp.Authorization.Users;
using Abp.Domain.Repositories;
using MyCompanyName.AbpZeroTemplate.Authorization.Users;
using MyCompanyName.AbpZeroTemplate.Prm.Admin;
using MyCompanyName.AbpZeroTemplate.Prm.Project;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyCompanyName.AbpZeroTemplate.Prm.Authorization
{
    public class PermissionService : AbpZeroTemplateDomainServiceBase
    {
        //项目角色权限
        private readonly IRepository<ProjectRoleFunctionActions> _projectRoleFunctionActionsRepository;
        //项目角色文档权限
        private readonly IRepository<ProjectRoleDocmentActions> _projectRoleDocmentActionsRepository;
        //系统角色权限
        private readonly IRepository<SystemRoleFunctionActions> _systemRoleFunctionActionsRepository;
        //系统角色文档权限
        private readonly IRepository<SystemRoleDocmentActions> _systemRoleDocmentActionsRepository;
        private readonly IRepository<ProjectFollower> _projectFollowerRepository;

        private readonly IRepository<UserQuan> _UserQuanRepository;
        private readonly IRepository<ProjectQuan> _ProjectQuanRepository;
        private readonly IRepository<TaskQuan> _TaskQuanRepository;
        private readonly IRepository<Quan> _QuanRepository;


        private readonly IRepository<ProjectInfo> _projectInfoRepository;
        IRepository<DocumentType> _docTypeRepository;
        private readonly IRepository<ProjectDocmeut> _projectDocRepository;
        private readonly IRepository<Inquiry.Inquiry> _inquiryRepository;

        private readonly IRepository<User, long> _userRepository;
        private readonly IRepository<ProjectTeam> _projectTeamRepository;

        private IRepository<UserRole, long> _userRoleRepository { get; set; }

        public PermissionService(
            IRepository<ProjectRoleFunctionActions> projectRoleFunctionActionsRepository,
            IRepository<ProjectRoleDocmentActions> projectRoleDocmentActionsRepository,
            IRepository<SystemRoleFunctionActions> systemRoleFunctionActionsRepository,
            IRepository<SystemRoleDocmentActions> systemRoleDocmentActionsRepository,
            IRepository<User, long> userRepository,


            IRepository<UserQuan> UserQuanRepository,
            IRepository<ProjectQuan> ProjectQuanRepository,
            IRepository<TaskQuan> TaskQuanRepository,
            IRepository<Quan> QuanRepository,

             IRepository<UserRole, long> userRoleRepository,
            IRepository<ProjectTeam> projectTeamRepository,
            IRepository<ProjectInfo> projectInfoRepository,
            IRepository<ProjectFollower> projectFollowerRepository,
            IRepository<ProjectDocmeut> projectDocRepository,
            IRepository<DocumentType> docTypeRepository,
            IRepository<Inquiry.Inquiry> inquiryRepository
            )
        {
            _inquiryRepository = inquiryRepository;
            _ProjectQuanRepository = ProjectQuanRepository;
            _TaskQuanRepository = TaskQuanRepository;
            _UserQuanRepository = UserQuanRepository;
            _QuanRepository = QuanRepository;
            _docTypeRepository = docTypeRepository;
            _projectDocRepository = projectDocRepository;

            _projectRoleFunctionActionsRepository = projectRoleFunctionActionsRepository;
            _projectRoleDocmentActionsRepository = projectRoleDocmentActionsRepository;
            _systemRoleFunctionActionsRepository = systemRoleFunctionActionsRepository;
            _systemRoleDocmentActionsRepository = systemRoleDocmentActionsRepository;
            _userRepository = userRepository;
            _projectTeamRepository = projectTeamRepository;
            _projectInfoRepository = projectInfoRepository;
            _userRoleRepository = userRoleRepository;
            _projectFollowerRepository = projectFollowerRepository;
        }

        public bool HasPermission(long userId, int projectId, ProjectFunctions action)
        {
            /*
             * 1、作为项目成员，同时拥有该权限；
             * **********需要判断是否过期（访客）-------直接判断过期
             * 
             * 2、系统角色，同时拥有该权限；
             * **********2.1判断当前他的权力圈，是否包含
             */
            DateTime dt = DateTime.Now.Date;

            var 项目成员 = _projectTeamRepository.GetAll().Where(x => x.UserId == userId && x.IsDeleted == false && x.EndTime >= dt && x.ProjectId == projectId).Select(x => x.ProjectRoleId);
            var 项目成员角色中含有该权限 = _projectRoleFunctionActionsRepository.GetAll().Any(x => 项目成员.Any(m => m == x.ProjectRoleId) && x.Permission == action);
            if (项目成员角色中含有该权限) return true;

            var user = _userRepository.Get(userId);
            var 用户的系统角色集合 = user.Roles.Select(x => x.RoleId).ToList();
            if (!用户的系统角色集合.Any(x => x > 0))
                return false;

            var 用户所有的系统角色中含有该权限 = _systemRoleFunctionActionsRepository.GetAll()
                .Where(x => x.Permission == action && 用户的系统角色集合.Any(m => m == x.SystemRoleId))
                .Select(x => x.ProjectScope)
                .Any();

            if (!用户所有的系统角色中含有该权限)
                return false;


            if (action == ProjectFunctions.项目新增)
            {
                return true;
            }

            // 若系统角色中含有该权限，再判断 用户和项目 圈是否能匹配
            var hasAuth = QuanDiff(projectId, userId);
            return hasAuth;
        }

        public bool IsMultipleUpload(int typeId)
        {
            if (typeId <= 0)
            {
                return false;
            }
            return _docTypeRepository.Get(typeId).DefaultUploadNum > 1;
        }

        public bool HasFollowedProject(long userId, int projectId)
        {
            return _projectFollowerRepository.GetAll().Any(x => x.IsDeleted == false && x.UserId == userId && x.ProjectId == projectId);
        }
        /// <summary>
        /// 批断项目圈与用户所有在圈是否匹配
        /// </summary>
        /// <param name="projectInfo"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool QuanDiff(int projectId, long userId)
        {
            // 用户的圈
            List<string> UserQuanCodes = _UserQuanRepository.GetAll().Where(x => x.UserId == userId).Select(x => x.QuanCode).ToList();
            var childIds = _UserQuanRepository.GetAll().Where(x => UserQuanCodes.Any(t => x.QuanCode.StartsWith(t))).Select(x => x.UserId).Distinct().ToList();
            var validQuanCodes = _UserQuanRepository.GetAll().Where(x => childIds.Contains(x.UserId)).Select(x => x.QuanCode).OrderBy(x => x).Distinct().ToList();

            var minValidQuanCodes = GetStartWithLst(validQuanCodes);


            if (minValidQuanCodes == null || minValidQuanCodes.Count == 0)
            {
                return false;
            }

            // 项目的圈
            List<string> ProjectQuanCodes;
            ProjectInfo projectInfo = _projectInfoRepository.Get(projectId);

            if (projectInfo.UsedMemberQuan)
            {

                // 取回成员的圈
                var userIds = _projectTeamRepository.GetAll().Where(x => x.IsDeleted == false && x.ProjectId == projectId && x.ProjectRoleId != ProjectConst.Visitor).Select(x => x.UserId);
                ProjectQuanCodes = _UserQuanRepository.GetAll().Where(x => userIds.Any(uid => uid == x.UserId)).Select(x => x.QuanCode).ToList();
            }
            else
            {
                // 使用 项目自定义的圈
                ProjectQuanCodes = _ProjectQuanRepository.GetAll().Where(x => x.ProjectId == projectId).Select(x => x.QuanCode).ToList();
            }
            if (ProjectQuanCodes == null || ProjectQuanCodes.Count == 0)
            {
                return false;
            }

            foreach (var userQ in minValidQuanCodes)
            {
                foreach (var projectQ in ProjectQuanCodes)
                {
                    // 用户圈 为 项目圈的前缀
                    if (projectQ.StartsWith(userQ))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private List<string> GetStartWithLst(List<string> aa)
        {
            List<string> bb = new List<string>();
            if (aa.Count > 0)
            {
                bb.Add(aa[0]);
                do
                {
                    var remove = aa.Where(t => bb.Any(x => t.StartsWith(x))).ToList();
                    int removeLen = remove.Count;
                    for (int i = 0; i < removeLen; i++)
                    {
                        aa.Remove(remove[i]);
                    }
                    if (aa.Count > 0)
                    {
                        bb.Add(aa[0]);
                        aa.RemoveAt(0);
                    }
                } while (aa.Count > 0);
            }

            return bb;
        }

        public bool HasPermission(int projectId, long userId, int docTypeId, DocmentFunctions action)
        {
            var 项目成员 = _projectTeamRepository.GetAll().Where(x => x.UserId == userId).Select(x => x.ProjectRoleId);
            var hasPrm = _projectRoleDocmentActionsRepository.GetAll()
                .Where(x => 项目成员.Any(m => m == x.ProjectRoleId) && x.DocTypeId == docTypeId && x.Permission == action)
                .Any();

            if (hasPrm) return true;

            var user = _userRepository.Get(userId);
            var 用户的系统角色集合 = user.Roles.Select(x => x.RoleId).ToList();
            if (!用户的系统角色集合.Any(x => x > 0))
                return false;

            var 用户所有的系统角色中含有该权限 = _systemRoleDocmentActionsRepository.GetAll()
                .Where(x => 用户的系统角色集合.Any(m => m == x.SystemRoleId) && x.Permission == action && x.DocTypeId == docTypeId)
                .Any();

            if (!用户所有的系统角色中含有该权限)
                return false;

            // 若系统角色中含有该权限，再判断 用户和项目 圈是否能匹配
            var hasAuth = QuanDiff(projectId, userId);
            return hasAuth;
        }

        public bool HasPermissionInquiry(long userId, int quiryId)
        {
            List<long> subUserIds = new List<long>();
            #region CreateIds+adminId
            var curQuanCodes = _UserQuanRepository.GetAll().Where(x => userId == x.UserId).Select(x => x.QuanCode).ToList();
            List<long> _subUserIds = _UserQuanRepository.GetAll().Where(x => curQuanCodes.Any(y => x.QuanCode.StartsWith(y))).Select(x => x.UserId).Distinct().ToList();
            subUserIds.AddRange(_subUserIds);
            subUserIds.Add(userId);
            #endregion


            var q = _inquiryRepository.Get(quiryId);

            if (subUserIds.Contains((long)q.CreatorUserId) || subUserIds.Contains(q.AdminId))
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 判定是否有下载文档的权限
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public bool HasDownLoadPermission(long userId, string path)
        {

            var proDocs = _projectDocRepository.GetAll().Where(x => x.FullUrl == path).ToList();
            foreach (var item in proDocs)
            {
                var _hasDownload = false;
                if (item.DocTypeId > 0)
                {
                    _hasDownload = HasPermission(item.ProjectId, userId, item.DocTypeId, DocmentFunctions.文档下载);
                }
                else
                {
                    _hasDownload = HasPermission(userId, item.ProjectId, ProjectFunctions.项目查看);
                }

                if (_hasDownload)
                {
                    return true;
                }
            }

            var inquirys = _inquiryRepository.GetAll().Where(x => x.Files.Contains(path) || x.SynthFiles.Contains(path)).ToList();
            foreach (var item in inquirys)
            {
                var _hasDownload = HasPermissionInquiry(userId, item.Id);
                if (_hasDownload)
                {
                    return true;
                }
            }

            return false;
        }



        public List<long> GetPermissionUsers(int proId, ProjectFunctions action)
        {

            List<int> projectRoleIds = _projectRoleFunctionActionsRepository.GetAll().Where(x => x.Permission == action).Select(x => x.ProjectRoleId).ToList();
            List<long> proUserIds = _projectTeamRepository.GetAll().Where(x => x.ProjectId == proId && projectRoleIds.Any(y => y == x.ProjectRoleId)).Select(x => x.UserId).ToList();

            List<int> sysRoleIds = _systemRoleFunctionActionsRepository.GetAll().Where(x => x.Permission == action).Select(x => x.SystemRoleId).ToList();
            List<long> sysUserIds = _userRoleRepository.GetAll().Where(x => sysRoleIds.Any(y => y == x.RoleId)).Select(x => x.UserId).ToList();

            List<long> _allPersionUserIds = new List<long>();
            _allPersionUserIds.AddRange(proUserIds);
            _allPersionUserIds.AddRange(sysUserIds);
            return _allPersionUserIds;
        }

        public bool HasSysPermission(long userId, ProjectFunctions action)
        {

            List<int> sysRoleIds = _systemRoleFunctionActionsRepository.GetAll().Where(x => x.Permission == action).Select(x => x.SystemRoleId).ToList();
            return _userRoleRepository.GetAll().Where(x => x.UserId == userId && sysRoleIds.Any(y => y == x.RoleId)).Any();

        }

    }
}
